package com.song.boot.springstudy.netty.idle.reconnect;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

public class ReconnectClient {
    private static final String HOST = "127.0.0.1";
    private static final int PORT = 8080;
    
    private Bootstrap bootstrap;
    private EventLoopGroup group;
    
    public static void main(String[] args) throws Exception {
        new ReconnectClient().start();
    }
    
    public void start() {
        group = new NioEventLoopGroup();
        bootstrap = new Bootstrap();
        
        bootstrap.group(group)
                 .channel(NioSocketChannel.class)
                 .handler(new ChannelInitializer<SocketChannel>() {
                     @Override
                     protected void initChannel(SocketChannel ch) throws Exception {
                         ChannelPipeline pipeline = ch.pipeline();
                         // 添加字符串编解码器
                         pipeline.addLast("decoder", new StringDecoder(StandardCharsets.UTF_8));
                         pipeline.addLast("encoder", new StringEncoder(StandardCharsets.UTF_8));
                         // 添加IdleStateHandler
                         pipeline.addLast("idleStateHandler", 
                                 new IdleStateHandler(0, 3, 0, TimeUnit.SECONDS));
                         
                         // 添加心跳和重连Handler
                         pipeline.addLast("heartbeatHandler", new ReconnectClientHandler(ReconnectClient.this));
                     }
                 });
        
        // 首次连接
        doConnect();
    }
    
    /**
     * 执行连接操作
     */
    protected void doConnect() {
        ChannelFuture future = bootstrap.connect(HOST, PORT);
        future.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (future.isSuccess()) {
                    System.out.println("连接服务端成功");
                } else {
                    System.out.println("连接服务端失败，5秒后尝试重连...");
                    
                    // 5秒后重连
                    future.channel().eventLoop().schedule(new Runnable() {
                        @Override
                        public void run() {
                            doConnect();
                        }
                    }, 5, TimeUnit.SECONDS);
                }
            }
        });
    }
    
    /**
     * 关闭资源
     */
    public void shutdown() {
        group.shutdownGracefully();
    }
}
